package com.example.limit.service;

import com.example.limit.entity.PurchaseRule;
import com.example.limit.mapper.PurchaseRecordMapper;
import com.example.limit.mapper.PurchaseRuleMapper;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
public class PurchaseLimitService {
    
    private final PurchaseRuleMapper ruleMapper;
    private final PurchaseRecordMapper recordMapper;
    private final RedisCounterService counterService;
    private final RedissonClient redissonClient;
    
    public PurchaseLimitService(PurchaseRuleMapper ruleMapper, PurchaseRecordMapper recordMapper, 
                               RedisCounterService counterService, RedissonClient redissonClient) {
        this.ruleMapper = ruleMapper;
        this.recordMapper = recordMapper;
        this.counterService = counterService;
        this.redissonClient = redissonClient;
    }
    
    /**
     * 校验购买限制
     */
    public boolean checkPurchaseLimit(Long userId, String productId, String categoryId, int quantity) {
        String lockKey = counterService.generateKey("purchase:lock", userId.toString(), productId);
        RLock lock = redissonClient.getLock(lockKey);
        
        try {
            if (lock.tryLock(3, 10, TimeUnit.SECONDS)) {
                // 获取所有生效的限购规则
                List<PurchaseRule> activeRules = getActiveRules();
                
                for (PurchaseRule rule : activeRules) {
                    if (!checkSingleRule(rule, userId, productId, categoryId, quantity)) {
                        return false;
                    }
                }
                return true;
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return false;
        } finally {
            lock.unlock();
        }
        return false;
    }
    
    @Cacheable(value = "activeRules", key = "'all'")
    public List<PurchaseRule> getActiveRules() {
        return ruleMapper.selectActiveRules();
    }
    
    private boolean checkSingleRule(PurchaseRule rule, Long userId, String productId, String categoryId, int quantity) {
        switch (rule.getRuleType()) {
            case 1: // 用户维度
                return checkUserDimensionRule(rule, userId, productId, categoryId, quantity);
            case 2: // 商品维度
                return checkProductDimensionRule(rule, userId, productId, categoryId, quantity);
            case 3: // 时间维度
                return checkTimeDimensionRule(rule, userId, productId, categoryId, quantity);
            case 4: // 订单维度
                return checkOrderDimensionRule(rule, userId, productId, categoryId, quantity);
            default:
                return true;
        }
    }
    
    private boolean checkUserDimensionRule(PurchaseRule rule, Long userId, String productId, String categoryId, int quantity) {
        String key;
        Duration expireTime;
        
        switch (rule.getSubType()) {
            case 1: // 单用户限购
                key = counterService.generateKey("user:limit", userId.toString(), productId);
                expireTime = Duration.between(LocalDateTime.now(), rule.getEndTime());
                break;
            case 2: // 新老用户
                // 这里需要用户服务判断新老用户，简化处理
                key = counterService.generateKey("user:type", userId.toString());
                expireTime = Duration.of(1, ChronoUnit.DAYS);
                break;
            default:
                return true;
        }
        
        return !counterService.isExceedLimit(key, rule.getLimitQuantity(), quantity, expireTime);
    }
    
    private boolean checkProductDimensionRule(PurchaseRule rule, Long userId, String productId, String categoryId, int quantity) {
        String key;
        Duration expireTime;
        
        switch (rule.getSubType()) {
            case 3: // 单品限购
                key = counterService.generateKey("product:limit", productId);
                expireTime = Duration.between(LocalDateTime.now(), rule.getEndTime());
                break;
            case 4: // 品类限购
                key = counterService.generateKey("category:limit", categoryId);
                expireTime = Duration.between(LocalDateTime.now(), rule.getEndTime());
                break;
            default:
                return true;
        }
        
        return !counterService.isExceedLimit(key, rule.getLimitQuantity(), quantity, expireTime);
    }
    
    private boolean checkTimeDimensionRule(PurchaseRule rule, Long userId, String productId, String categoryId, int quantity) {
        String key = counterService.generateKey("time:limit", userId.toString(), productId, 
                                              rule.getStartTime().toString(), rule.getEndTime().toString());
        Duration expireTime = Duration.between(LocalDateTime.now(), rule.getEndTime());
        
        return !counterService.isExceedLimit(key, rule.getLimitQuantity(), quantity, expireTime);
    }
    
    private boolean checkOrderDimensionRule(PurchaseRule rule, Long userId, String productId, String categoryId, int quantity) {
        String key;
        Duration expireTime;
        
        switch (rule.getSubType()) {
            case 6: // 单订单限购
                // 订单维度在创建订单时校验，这里简化处理
                return quantity <= rule.getLimitQuantity();
            case 7: // 多订单累计
                key = counterService.generateKey("order:accumulate", userId.toString(), productId);
                expireTime = Duration.between(LocalDateTime.now(), rule.getEndTime());
                break;
            default:
                return true;
        }
        
        return !counterService.isExceedLimit(key, rule.getLimitQuantity(), quantity, expireTime);
    }
}